#include "StdAfx.h"
#include "ProjectionOperator.h"
#include "QueueEntity.h"
#include "DocumentIdentifierGenerator.h"
ProjectionOperator::ProjectionOperator(std::set<std::string> projectionAttributeSet)
{
	int lineageNumber  = 1;
	this->lineageSynopsis.reset(new LineageSynopsis(lineageNumber));
	this->projectionAttributeSet = projectionAttributeSet;
}


ProjectionOperator::~ProjectionOperator(void)
{
}


void ProjectionOperator::execution(int executionTimes)
{
#ifdef DEBUG
	std::cout<<"===================operator begin================="<<std::endl;
	std::cout<<"operatorid : "<<this->getId()<<std::endl;
#endif
	assert(this->getInputQueueList().size()==1);
	assert(this->getOutputQueueList().size()==1);
	boost::shared_ptr<QueueEntity>inputQueue = this->getInputQueueList().front();
	boost::shared_ptr<QueueEntity>outputQueue = this->getOutputQueueList().front();
	bool ret;
	for(int i = 0; i<executionTimes ;i++)
	{
		Element inputElement;
		if(outputQueue->isFull())
		{
			break;
		}
		if(inputQueue->isEmpty())
		{
			break;
		}
		inputQueue->dequeue(inputElement);
		if(inputElement.mark == PLUS_MARK)
		{
			// Produce new document
			Document newDocument;
			Document inputDocument = inputElement.document;
			newDocument.addFields(inputDocument,projectionAttributeSet);

			// Produce the output element
			Element outputElement;
			outputElement.id = DocumentIdentifierGenerator::generateNewDocumentIdentifier();
			outputElement.mark = PLUS_MARK;
			outputElement.timestamp = inputElement.timestamp;
			outputElement.document = newDocument;

			//enqueue the output element
			outputQueue->enqueue(outputElement);

			//insert into the lineage synopsis
			if(lineageSynopsis->isFull())
			{
				throw std::runtime_error("synopsis is full");
			}
			Lineage lineage;
			lineage.lineageNumber = 1;
			lineage.lineageDocumentId[0] = inputElement.id;
			lineageSynopsis->insertLineage(lineage,outputElement);

		}
		else if(inputElement.mark  == MINUS_MARK)
		{
			Element elementInSynopsis;
			Lineage lineage;
			lineage.lineageNumber = 1;
			lineage.lineageDocumentId[0] = inputElement.id;
			ret = lineageSynopsis->getAndDeleteElement(lineage,elementInSynopsis);
			if(ret==false)
			{
				throw std::runtime_error("lineage not exist");
			}
			Element outputElement;
			outputElement.mark = MINUS_MARK;
			outputElement.document = elementInSynopsis.document;
			outputElement.timestamp = inputElement.timestamp;
			outputElement.id = elementInSynopsis.id;
			outputQueue->enqueue(outputElement);
		}
	}
#ifdef DEBUG
	std::cout<<"===================operator over================="<<std::endl;
#endif
}